import React from "react";
import './App.css';
import './loading.css';

//测试用
// import T from './T';

import { getName } from '@tauri-apps/api/app';
import { Command } from '@tauri-apps/api/shell';
import { resourceDir, join, dirname, localDataDir } from '@tauri-apps/api/path';
import { window } from "@tauri-apps/api";
import { BaseDirectory, exists, createDir, removeDir, readDir, copyFile, removeFile } from '@tauri-apps/api/fs';

const staticResourceDir = [

];
const staticResourceFile = [
  "dbs/shell.db"
];

const resourceEnv = { dir: BaseDirectory.Resource, recursive: true };

const pidReg = /APP PID WITH : ([0-9]+)/;
const baseApiPath = "http://localhost:38888";
const jarName = "fairyshell-1.0.jar";

//外部资源
const jarPath = `../../jar/${jarName}`;

function getDialectCommand() {
  var userAgent = navigator.userAgent;
  if (userAgent.indexOf("Windows", 0) !== -1) {
    return {
      killJava: pId => new Command("cmd", [`/c taskkill /pid ${pId} /f`]),
      startJava: {
        cmd: "cmd",
        command: param => [`/C`, `java`, `-jar`, `-Dfile.encoding=utf-8`, `${param}`, `${jarPath}`]
      }
    }
  }
  if (userAgent.indexOf("Linux", 0) !== -1) {
    return {
      killJava: pId => new Command("kill", [`-9 ${pId}`]),
      startJava: {
        cmd: "./java",
        command: param => [`-jar`, `-Dfile.encoding=utf-8`, `${param}`, `${jarPath}`]
      }
    }
  }
  if (userAgent.indexOf("Mac", 0) !== -1) {
    return {
      killJava: pId => new Command("kill", [`-9 ${pId}`]),
      startJava: {
        cmd: "./java",
        command: param => [`-jar`, `-Dfile.encoding=utf-8`, `${param}`, `${jarPath}`]
      }
    }
  }
}

let child = null;
let javaPid = null;
let dialectCommand = getDialectCommand();
window.getCurrent().onCloseRequested(async (e) => {
  if (!!javaPid && !!dialectCommand) {
    try {
      await dialectCommand.killJava(javaPid).execute();
    } catch (e) {
    }
  }
  !!child && await child.kill();
  window.getCurrent().close();
})

class App extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      info: "启动中，请稍等...",
      showUI: false
    }
    this.resourcePath = null;
    this.appDataPath = null;
  }

  async componentDidMount() {
    //生产打开
    document.oncontextmenu = () => { return false; }

    await this.initPath();

    for (const resource of staticResourceDir) {
      await this.processDir(resource);
    }

    for (const file of staticResourceFile) {
      await this.processFile(file);
    }

    this.startJar()
      .then(this.init.bind(this))
      .catch(e => this.setState({ info: `出错了...... : ${e}` }));
  }

  async initPath() {
    this.resourcePath = await resourceDir();
    if (this.resourcePath.startsWith("\\\\?\\") ||
      this.resourcePath.startsWith("\\\\.\\")) {
      this.resourcePath = this.resourcePath.substring(4);
    }
    console.log("resourcePath:", this.resourcePath);

    let localDataPath = await localDataDir();
    this.appDataPath = await join(localDataPath, await getName());
    console.log("appDataPath:", this.appDataPath);
  }

  init() {
    this.setState({ showUI: true });
  }

  async processDir(sourceDir) {
    let targetDir = await join(this.appDataPath, sourceDir);
    let sourceExists = await exists(sourceDir, resourceEnv);
    let targetExists = await exists(targetDir);
    if (!sourceExists || !!targetExists) {
      return;
    }

    await createDir(targetDir, { recursive: true });

    const entries = await readDir(sourceDir, resourceEnv);
    for (const entry of entries) {
      let ePath = entry.path;
      ePath = ePath.substring(ePath.indexOf(this.resourcePath), ePath.length);
      let nextPath = ePath.replace(this.resourcePath, "");

      if (!entry.children) {
        await this.processFile(nextPath);
      } else {
        await this.processDir(nextPath);
      }
    }
  }

  async processFile(sourceFile) {
    let sourceExists = await exists(sourceFile, resourceEnv);
    let targetFilePath = await join(this.appDataPath, sourceFile);
    let targetExists = await exists(targetFilePath);
    if (!sourceExists || !!targetExists) {
      return;
    }

    let targetParentPath = await dirname(targetFilePath);
    await createDir(targetParentPath, { recursive: true });

    let sourceAbsPath = await join(this.resourcePath, sourceFile);
    await copyFile(sourceAbsPath, targetFilePath);
  }

  startJar() {
    return new Promise(async (resolve, reject) => {
      let testResult = await this.testJar();
      console.log("testResult : " + testResult);
      if (testResult) {
        resolve();
        return;
      }

      if (!dialectCommand) {
        reject(new Error("不支持的系统"));
        return;
      }

      let commandPath = await join(this.resourcePath, "jre", "bin");
      console.log("commandPath", commandPath);

      try {
        let command = new Command(dialectCommand.startJava.cmd,
          dialectCommand.startJava.command(`-DLOCALAPPDATA=${this.appDataPath}`),
          { cwd: commandPath });

        command.on('error', console.error);
        command.stderr.on("data", console.error);

        command.stdout.on('data', line => {
          console.log(line);
          if (line.match(pidReg)) {
            javaPid = pidReg.exec(line)[1];
          }
          if (line.indexOf("Started RuoYiApplication") !== -1) {
            resolve();
            return;
          }
          if (line.indexOf("Exception") !== -1) {
            reject(line);
            return;
          }
        });

        child = await command.spawn();
      } catch (e) {
        console.error("command error", e);
        reject(e);
      }
    });
  }

  async testJar() {
    return new Promise(resolve => {
      fetch(`${baseApiPath}/ssh/manage/ping`)
        .then(r => resolve(r.status == 200))
        .catch(e => resolve(false));
      setTimeout(() => {
        resolve(false);
      }, 500);
    });
  }

  render() {
    let { showUI, info } = this.state;
    return (
      <>
        {
          // showUI ? <T /> :
          //   <>
          //     <div className="loading">
          //       <span></span>
          //       <span></span>
          //       <span></span>
          //       <span></span>
          //       <span></span>
          //     </div>
          //     <div className="loading">加载中，请稍等...</div>
          //   </>
          showUI ? <iframe src="./app/"
            style={{
              border: 0,
              width: "100%",
              height: "100%"
            }} /> :
            <>
              <div className="loading">
                <span></span>
                <span></span>
                <span></span>
                <span></span>
                <span></span>
              </div>
              <div className="loading">{info}</div>
            </>
        }
      </>
    );
  }

}

export default App;
